1)  Install DeusEx, DeusEx SDK and extract the DeusEx Source.  Instructions on how to extract the DeusEx Source can be found at the bottom of the file.

2) Have you ever played CounterStrike?  Ask a stupid question.  Well you'd know that some bullets will go through walls, this will make a new sniper rifle and it will let bullets pass through one wall.

3)  Make a new directory: c:\deusex\mm and c:\deusex\mm\Classes.  If you have followed any of my previous tutorials, then you might have a file or two in the classes subdirectory; just delete them now or change their file extensions from .uc then they won't be compiled.

4) Make a new text file called and put it in: c:\deusex\mm\Classes\mmweaponrifle.uc.  Open it in wordpad or whatever text editor you prefer.  Type the following text into the file:

class mmWeaponRifle extends WeaponRifle;

// Wall penetration 
var() float Thick; 
// Pawn penetration 
var() float PawnThick;

// FUNCTION FROM C:\DEUSEX\ENGINE\CLASSES\WEAPON.UC 
function TraceFire( float Accuracy ) 
    { 
     local vector HitLocation, HitNormal, StartTrace, EndTrace, X,Y,Z; 
     local actor Other; 
     local Pawn PawnOwner; 
     local float Penetration;

     PawnOwner = Pawn(Owner);

     Owner.MakeNoise(PawnOwner.SoundDampening); 
     GetAxes(PawnOwner.ViewRotation,X,Y,Z); 
     // STANDARD BULLET POSITION CHECKING CODE

     StartTrace = Owner.Location + CalcDrawOffset() + FireOffset.X * X 
     + FireOffset.Y * Y + FireOffset.Z * Z;  
     AdjustedAim = PawnOwner.AdjustAim(1000000, StartTrace, 2*AimError, False, False);  
     EndTrace = StartTrace + Accuracy * (FRand() - 0.5 )* Y * 1000 
     + Accuracy * (FRand() - 0.5 ) * Z * 1000; 
     X = vector(AdjustedAim); 
     EndTrace += (10000 * X);  
     Other = PawnOwner.TraceShot(HitLocation,HitNormal,EndTrace,StartTrace);

     // TELLS DEUSEX TO 'HIT' THE FIRST THING IT FINDS 
     ProcessTraceHit(Other, HitLocation, HitNormal, X,Y,Z);

     // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

     if (Other.IsA('Pawn')) 
         Penetration = PawnThick; 
            else 
             Penetration = Thick; 
             StartTrace = HitLocation + HitNormal + (Penetration * X); 
             EndTrace = StartTrace + Accuracy * (FRand() - 0.5 )* Y * 1000 
             + Accuracy * (FRand() - 0.5 ) * Z * 1000; 
             EndTrace += (10000 * X); 
             Other = PawnOwner.TraceShot(HitLocation,HitNormal,EndTrace,StartTrace); 
             // Hit second object and stop, do not pass through them. 
             ProcessTraceHit(Other, HitLocation, HitNormal, X,Y,Z); 
         }

defaultproperties 
{ 
Thick=20.0 
PawnThick=36.0 
}

A lot of text.  Check you have it all!  Now let's work out what each bit does. 
Ok?

5)  Read this text below:

var() float Thick; 
This sets the bullet penetration through walls.  More about this later.

var() float PawnThick; 
This sets the bullet penetration through pawns.  Again, more about this later.

local vector HitLocation, HitNormal, StartTrace, EndTrace, X,Y,Z; 
local actor Other; 
local Pawn PawnOwner; 
local float Penetration;

These should be fairly obvious.  Some decimal point numbers, a pawn to set the bullet's control to, adds an actor and calls it Other and adds a bucket load of vector's.  We'll need all this later.

PawnOwner = Pawn(Owner);

Sets the pawn owner.

Actually, the first bit of this function, up to the xxx's, is the TraceFloat function from c:\deusex\engine\classes\weapon.uc.  Have a read of the TraceFloat function in there before continuing.  I'll wait for you... 
... 
(drinks Pepsi Light) 
... 
Ah, you're back!  Let's get on!

6)  Read the bit below xxx's.  I'll paste it below so you don't have to scroll up:

     if (Other.IsA('Pawn')) 
         Penetration = PawnThick; 
            else 
             Penetration = Thick; 
             StartTrace = HitLocation + HitNormal + (Penetration * X); 
             EndTrace = StartTrace + Accuracy * (FRand() - 0.5 )* Y * 1000 
             + Accuracy * (FRand() - 0.5 ) * Z * 1000; 
             EndTrace += (10000 * X); 
             Other = PawnOwner.TraceShot(HitLocation,HitNormal,EndTrace,StartTrace); 
             // Hit second object and stop, do not pass through them. 
             ProcessTraceHit(Other, HitLocation, HitNormal, X,Y,Z); 
         }

Look at the first line:

if(Other.IsA('Pawn'))

Now look at an earlier line:

local actor Other;

More helpfully, look at this line in the standard weapon.uc:

Other = PawnOwner.TraceShot(HitLocation,HitNormal,EndTrace,StartTrace);

Which, I think, just sets whatever got hit by the last bullet to Other. 

So our first line checks to see if Other is a pawn (i.e. like a badguy), it sets Penetration = PawnThick. Pentration is a previously unused variable, and PawnThick is apparently the default thickness of any wall plus a bit to allow bullet travel; else it sets Penetration to be the thickness of a default pawn plus just a little bit for travel.

StartTrace = Owner.Location + CalcDrawOffset() + FireOffset.X * X

The line above is the standard 'trace' (bullet path) for only hitting one object.

StartTrace = HitLocation + HitNormal + (Penetration * X);

This is the line for the second trace.  We can use HitLocation and HitNormal from ProcessTraceHit to set the bullet's position (as ProcessTraceHit records where the bullet hit); and add the Penetration (remember, that is the thickness of either a wall or a pawn) multiplied by the X position of the bullet.

7)  Save the file.  You only need to copy the text in stage four into mmweaponrifle.uc, the rest and the other code examples are just an explanation of it.

8)  Add EditPackages=MM in the normal section in the deusex.ini file.  Save and close it.  Open a DOS window, goto c:\deusex\system, and type:

ucc make

(Remembering to see if c:\deusex\system\mm.u exists, and if so, to delete it.) 
 

Load up a map, in the console type:

summon mm.mmweaponrifle

Now find a door, make sure it's closed, wait for a man to walk past and shoot.  The bullet will pass through the door and it might even take him down, if you've aimed well enough and/or have a high enough rifle skill level.  Until next time...

Thank you for using this tutorial!  Email me at boneskull62@hotmail.com with your opinion or post them on Modus Moriendi's message board or this message board.